package org.fei.ClassDiagram;

import org.fei.ClassDiagram.WindowComponents.Message;
import java.util.List;
import org.netbeans.api.project.Project;
import org.openide.filesystems.FileObject;
import org.netbeans.spi.project.support.ProjectOperations;
import java.io.File;
import java.util.ArrayList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.netbeans.api.project.ProjectUtils;
import org.openide.filesystems.FileStateInvalidException;
import org.openide.util.Exceptions;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import java.net.URL;

/**
 * Trieda ma za ulohu zistit informacie o projekte.
 * Testovat projekt ci je spustitelna java aplikacia a najst class subory projektu.
 * 
 * @author      Tomas Gazovic <gazovic.tomas@gmail.com>
 * @version     1.0
 * @since       2011-10-16
 * 
 */
public class ProjectScanner {

    private FileObject projectXml;
    private FileObject projectProperties;
    private String projectName;
    private String projectType;
    private FileObject buildImplXml;

    public ProjectScanner(Project p) {

        // vrati metadata o projekte, medzi datami je aj nbproject adresar
        List<FileObject> fo = ProjectOperations.getMetadataFiles(p);
        for (FileObject f : fo) {
            if (f.isFolder()) {
                this.findFiles(f, "project", "xml");
                this.findFiles(f, "project", "properties");
                this.findFiles(f, "build-impl", "xml");
            }
        }

        this.parseTypeFromProjectXml();

        projectName = ProjectUtils.getInformation(p).getDisplayName();
    }

    /**
     * Rekurzivne prehladava adresare hlavneho projektu.
     * 
     * 
     * @param objekt typu FileObjekt moze byt bud subor alebo adresar. 
     */
    private void findFiles(FileObject object, String fileName, String extension) {

        FileObject[] objects = object.getChildren();
        for (int i = 0; i < objects.length; i++) {
            findFiles(objects[i], fileName, extension);

            if (fileName.equals(objects[i].getName()) && objects[i].hasExt(extension)) {
                if (fileName.equals("project") && extension.equals("xml")) {
                    this.projectXml = objects[i];
                }
                if (fileName.equals("project") && extension.equals("properties")) {
                    this.projectProperties = objects[i];
                }
                if (fileName.equals("build-impl") && extension.equals("xml")) {
                    this.buildImplXml = objects[i];
                }
            }
        }

        if (objects.length == 0) {
            return;
        }
    }

    public void findFiles(FileObject object, String extension, ArrayList<String> resultsPath) {

        FileObject[] objects = object.getChildren();
        for (int i = 0; i < objects.length; i++) {
            findFiles(objects[i], extension, resultsPath);

            if (objects[i].hasExt(extension)) {
                resultsPath.add(objects[i].getPath());
            }
        }

        if (objects.length == 0) {
            return;
        }
    }

    /*
     *  Podobne ako findFiles ale vracia list URL adries suborov ktore najde
     *  resultsURL je vystupny parameter funkcie
     */
    public void findFilesURL(FileObject object, String extension, ArrayList<URL> resultsURL) {

        FileObject[] objects = object.getChildren();
        for (int i = 0; i < objects.length; i++) {
            findFilesURL(objects[i], extension, resultsURL);

            if (objects[i].hasExt(extension)) {
                try {
                    resultsURL.add(objects[i].getURL());
                } catch (FileStateInvalidException ex) {
                    Exceptions.printStackTrace(ex);
                }
            }
        }

        if (objects.length == 0) {
            return;
        }
    }

    /*
     * nacitava typ projektu zo suboru project.xml element <type></type>
     *
     */
    private void parseTypeFromProjectXml() {

        try {
            File file = new File(projectXml.getPath());
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            Document doc = db.parse(file);
            doc.getDocumentElement().normalize();

            NodeList typElement = doc.getElementsByTagName("type");
            projectType = typElement.item(0).getFirstChild().getNodeValue();

        } catch (Exception ex) {
            Message.showMessage(ex.getMessage());
        }
    }

    /*
     * ak je typ projektu podporovana java aplikacia, vrati true inak false
     * zatial sa podporuje len java SE apliakacia
     */
    public boolean isProjectValid() {
        if (projectType.equals("org.netbeans.modules.java.j2seproject")) {
            return true;
        }
        //if (typProjektu.equals("org.netbeans.modules.web.project"))
        //    return true;      
        return false;
    }

    public FileObject getBuildImplXml() {
        return buildImplXml;
    }

    public String getProjectName() {
        return projectName;
    }

    public FileObject getProjectProperties() {
        return projectProperties;
    }
}
